关于jsp:HTTP状态-500-内部服务器错误

问题:明天因为启动本地tomcat拜访index.jsp都是能够的,然而新建了一个jsp页面就不可能拜访了。起因:是因为我一开始Jsp页面有谬误的,每一个jsp页面都会被web容器编译成一个java类,供web容器调用,并且宣称html页面回馈给用户。也就是你我的项目外面的target文件对应的login.jsp,如果不清理的话就会始终是之前谬误的Jsp。 解决方案:删除target文件夹或者是删除login.jsp当前重启tomcat。

August 26, 2022 · 1 min · jiezi

关于jsp:JSP实现文件上传功能

这篇文章次要为大家具体介绍了JSP实现文件上传性能,文中示例代码介绍的十分具体,具备肯定的参考价值,感兴趣的小伙伴们能够参考一下 本文实例为大家分享了JSP实现文件上传性能的具体代码,供大家参考,具体内容如下 一、筹备局部须要fileupload.jar与io.jar包共同完成。构建实现门路后可持续。 资源地址 二、页面局部 <form action="UploadServlet" method="post" enctype="multipart/form-data"> 学号:<input type="text" name="sno"/><br/> 姓名:<input type="text" name="sname"/><br/> 上传照片:<input type="file" name="spicture"/><br/> <input type="submit" value="注册"/></form>留神: 1.文件上传必须要应用post,以防止用get办法时传输总量超过搜寻框所能承载最大字符数。 2.必须退出enctype="multipart.form-data"字段 3.文件处需用“file” 三、Servlet局部 package webtest; import java.io.File;import java.io.IOException;import java.util.Iterator;import java.util.List; import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.FileItemFactory;import org.apache.commons.fileupload.FileUploadBase;import org.apache.commons.fileupload.FileUploadException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload; /** * Servlet implementation class UploadServlet */@WebServlet("/UploadServlet")public class UploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8");// 申请编码解决,传输时 response.setCharacterEncoding("utf-8");// 响应编码解决,传输时 response.setContentType("utf-8");// 响应编码解决,显示时 boolean isMultipart = ServletFileUpload.isMultipartContent(request);// 判断是否有entype="multipart/form-data"局部 if (isMultipart) { try { FileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); //设置上传时的内存缓冲区大小,超出时写入临时文件 10kb ((DiskFileItemFactory) factory).setSizeThreshold(10240);//单位byte //设置长期文件目录,避免零碎空间有余 ((DiskFileItemFactory) factory).setRepository(new File(request.getSession().getServletContext().getRealPath("Uploadtemp")));//动静获取Uploadtemp文件夹位于该我的项目中的地位 //管制上传单个文件的最大值 20kb upload.setSizeMax(20480);//单位byte List<FileItem> items = upload.parseRequest(request);// 解析form中的所有申请字段,并保留在item中 Iterator<FileItem> iter = items.iterator(); while (iter.hasNext()) { // 解析时无程序,因而需依据名字查找 FileItem item = iter.next(); if (item.isFormField()) {//非文件数据 String itemName = item.getFieldName();//获取非文件的范畴数据名 if (itemName.equals("sno")) { int sno = -1; sno = Integer.parseInt(item.getString("utf-8")); } else if (itemName.equals("sname")) { String sname = null; sname = item.getString("utf-8"); } else { System.out.println("其余字段..."); } } else {//文件上传 String fileName = item.getName();//获取文件范畴数据。门路及其名称 //判断文件类型 String ext = fileName.substring(fileName.indexOf(".")+1); if(!(ext.equals("png")||ext.equals("gif")||ext.equals("jpg"))) { System.out.println("仅反对png.gif,jpg类型文件"); return ; } String path = request.getSession().getServletContext().getRealPath("Upload");//动静获取Upload文件夹位于该我的项目中的地位 File file = new File(path,fileName); item.write(file);//定义上传门路,多为服务器门路 System.out.println(fileName+"上传胜利"); } item.delete();//删除长期目录的文件 } } catch(FileUploadBase.SizeLimitExceededException e) { System.out.println("最大20KB"); } catch (FileUploadException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }注: ...

June 25, 2022 · 2 min · jiezi

关于jsp:JSP

)

April 5, 2022 · 1 min · jiezi

关于jsp:jsp正确使用session完成猜数游戏完整版-优化版

游戏要求: 代码实现: c1_caishu_.jsp: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>Insert title here</title></head><body> 请输出一个1~20的整数进行猜数!<% int num = (int)Math.random()*20+1; session.setAttribute("count", new Integer(0));//猜数的次数 session.setAttribute("randomNum", new Integer(num));//产生的随机数%><form action="c1_caishu_judge.jsp" method="post"> <input type="text" name="guess"> <input type="submit" name="tijiao" value="提交"></form></body></html>c1_caishu_judge.jsp: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>Insert title here</title></head><body><% String str = request.getParameter("guess");//request.getParameter返回的是String类型 if(str==null && str.length()==0){ response.sendRedirect("c1_caishu_.jsp"); }else{ int userGuessNum = Integer.parseInt(str);//用户猜的数 session.setAttribute("guessNum", new Integer(userGuessNum)); Integer randomNum = (Integer)session.getAttribute("randomNum");//生成的随机数 if(userGuessNum == randomNum.intValue()){//猜对了 int n = ((Integer)session.getAttribute("count")).intValue();//猜数的次数 n++; session.setAttribute("count", new Integer(n)); response.sendRedirect("c1_caishu_success.jsp"); }else if(userGuessNum > randomNum.intValue()){//猜大了 int n = ((Integer)session.getAttribute("count")).intValue();//猜数的次数 n++; session.setAttribute("count", new Integer(n)); response.sendRedirect("c1_caishu_large.jsp"); }else{ //猜小了 int n = ((Integer)session.getAttribute("count")).intValue();//猜数的次数 n++; session.setAttribute("count", new Integer(n)); response.sendRedirect("c1_caishu_small.jsp"); } }%></body></html>c1_caishu_large.jsp ...

June 30, 2021 · 1 min · jiezi

关于jsp:学习笔记关于Servlet

Servlet和JSP的区别和分割HTML全称 Hyper Text Markup Language超文本标记语言,是一种标记语言。它包含一系列标签.通过这些标签能够将网络上的文档格局对立,使扩散的Internet资源连贯为一个逻辑整体。HTML文本是由HTML命令组成的描述性文本,HTML命令能够阐明文字,图形、动画、声音、表格、链接等,能够对立了解为动态Web资源。 JSP全称JavaServer Pages动静网页创立规范,部署于网络服务器上,Jsp以Java语言作为脚本,为用户的Http申请提供服务,并且与服务器上的其余Java程序独特解决简单的业务需要,生成动静HTML。 问题:用户在拜访静态数据(图片,文字...)的时候间接返回动态页面,用户拜访在拜访动态数据的时候须要连贯数据库,进行相应的逻辑解决,拿取用户申请的数据,那么服务器是如何辨认解决逻辑的呢?(通过Servlet) Servlet全称Servlet Applet服务器连接器,用Java语言编写的服务器端程序,具备独立于平台和协定的个性,次要性能在于交互式地浏览和生成数据,生成动静Web内容,广义的Servlet是指Java语言实现的一个接口,狭义的Servlet是指任何实现了这个Servlet接口的类,个别状况下,人们将Servlet了解为后者。Servlet运行于反对Java的应用服务器中。从原理上讲,Servlet能够响应任何类型的申请,但绝大多数状况下Servlet只用来扩大基于HTTP协定的Web服务器。 关系和分割1.Web容器将Jsp编译成了jvm可能辨认的Servlet(Java类),Jsp的实质是Servlet。2.Jsp侧重于前端的视图,Servlet侧重于逻辑管制。3.Servlet没有内置对象。4.Jsp中的内置对象由HttpServletRequest,HttpServletResponse,HttpServlet对象的到。 Servlet我的项目的开发步骤一:创立Servlet实现Servlet的一个接口或者继承Servlet的子类(GenericServlet/HttpServlet),并实现其办法。web工程目录文件的阐明 (1) Servlet: 工程名称/项目名称(2) src: 源码目录, 创立的java源文件、配置文件(properties、xml文件等)都能够放在src源码目录下(3) build/classes: 编译文件的输入目录, src源码目录中的文件编译后会输入到classes目录下。 其中的classes目录在公布时会放在WEB-INF目录下,随着我的项目一起公布到服务器中(4) WebContent: 就是Web利用的目录,其中能够寄存 html、css、js、jsp、图片以及编译后的class文件、jar包、web.xml文件等. 未来公布我的项目到服务器,其实就是将WebContent中的所有内容一起公布到服务器中。(5) WebContent/WEB-INF/lib: 用于寄存以后我的项目所依赖的jar包。比方要拜访mysql数据库,须要导入mysql驱动包,间接将jar包拷贝到lib目录下即可!(也不必再去做 build path --> add to build path)步骤二:创立Web的拜访门路,即配置web.xml<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Servlet</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <servlet> <description></description> <display-name>ServletDemo</display-name> <servlet-name>ServletDemo</servlet-name> <servlet-class>MTingCat.pra.ServletDemo</servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletDemo</servlet-name> <url-pattern>/ServletDemo</url-pattern> </servlet-mapping></web-app>a) Eclipse每创立一个Servlet,就会在web.xml文件中增加两个标签:<servlet>和<servlet-mapping>标签(能够将这两个标签看成一个组的标签) b) <servlet>和<servlet-mapping>标签内都会有一个<servlet-name>标签,标签的内容能够更改,但要求更改后的这两个<servlet-name>标签的内容也必须统一。 c) <servlet-class>标签用于配置Servlet类的全限定类名(即包名+类名) 须要留神:如果在创立Servlet后批改了Servlet类的名称,这个中央也要一起更改,否则将会呈现"ClassNotFoundException" 即类找不到异样 d) <url-pattern>标签用于配置浏览器以什么门路拜访以后Servlet(即Servlet对外拜访的门路),默认的门路是:/类名 例如:下面为HelloServlet配置的<url-pattern>为/HelloServlet,因而咱们在浏览器中的拜访门路则为: [http://主机名/web]我的项目拜访门路http://localhost:8089/Servlet/ServletDemo 步骤三:运行于Web端服务器(Tomcat) ...

February 1, 2021 · 1 min · jiezi

关于jsp:基于ssm框架实现的视频电影系统

我的项目介绍本零碎应用Spring+SpringMVC+MyBatis架构,数据库应用MySQL,共分为以下四大模块: 登录注册及用户治理提供登录注册以及集体根本材料的批改查问 资源管理管理员从后端增加电影资源并赋予资源的信息如名称、图片、时长、电影上映工夫、评分、导演、演员、类型、地区等信息,公布胜利在后端以及用户页面军可查看播放。 评论治理在减少互动性且保护良好环境的同时,对用户评论内置了敏感词汇过滤。 珍藏治理用户能够将喜爱的电影增加到珍藏核心,便于随时观看影片。 我的项目适用人群正在做毕设的学生,或者须要我的项目实战练习的Java学习者 开发环境:jdk 8intellij ideatomcat 8.5.40mysql 5.7所用技术:Spring+SpringMVC+MyBatislayuijsp我的项目拜访地址前端拜访地址 http://localhost:8090/index后盾拜访地址 http://localhost:8090/admin/indexadmin/admin我的项目截图首页 热门电影 电影详情 电影播放 后端-敏感词 后端-评估列表 后端-珍藏列表 后端-用户列表 数据库配置数据库配置信息#配置文件jdbc.url=jdbc:mysql://localhost:3306/movies?characterEncoding=UTF-8jdbc.driverClass=com.mysql.jdbc.Driverjdbc.username=rootjdbc.password=root123数据库配置加载<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 引入配置文件 --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:pro.properties" /> </bean> <!-- 定义数据源Bean --> <!-- Druid --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driverClass}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- 注册SqlSessionFactoryBean --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 主动扫描mappers.xml文件 --> <property name="mapperLocations" value="classpath*:com/lrfalse/dao/**/*.xml" /> <property name="configLocation" value="classpath:mybatis-config.xml"></property> </bean> <!-- DAO接口所在包名,Spring会主动查找其下的类 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.lrfalse.dao" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean> <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean></beans>springMvc配置<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 启动主动扫描 --> <context:component-scan base-package="com.lrfalse" /> <!-- 注册MVC注解驱动 --> <mvc:annotation-driven /> <!-- 动态资源可拜访的设置形式 --> <mvc:default-servlet-handler /> <mvc:resources location="/resource/" mapping="/resource/**" /> <mvc:resources location="/" mapping="/**/*.js"/> <mvc:resources location="/" mapping="/**/*.css"/> <mvc:resources location="/" mapping="/**/*.mp4"/> <mvc:resources location="/assets/" mapping="/assets/**/*"/> <mvc:resources location="/3rd/" mapping="/assets/**/*"/> <mvc:resources location="/assets/pc" mapping="/assets/pc/**/*"/> <!--拆卸Swagger配置--> <bean class="com.lrfalse.common.SwaggerConfig"/> <!--防止IE执行AJAX时,返回JSON呈现下载文件 --> <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> <!--减少tkmybatis注解依赖--> <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.lrfalse.dao"/> <property name="beanName" value="normal"/> </bean> <!-- 配置视图解析器,能够显式设置,也能够不设置,不设置会根据SpringMVC的默认设置 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> <!-- 配置文件上传,如果没有应用文件上传能够不必配置,当然如果不配,那么配置文件中也不用引入上传组件包 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 默认编码 --> <property name="defaultEncoding" value="utf-8" /> <!-- 文件大小最大值 --> <property name="maxUploadSize" value="10485760000" /> <!-- 内存中的最大值 --> <property name="maxInMemorySize" value="40960" /> </bean></beans>web.xml 配置<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1" metadata-complete="true"> <display-name>Archetype Created Web Application</display-name> <welcome-file-list> <welcome-file>/index</welcome-file> </welcome-file-list> <!-- Spring和mybatis的配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mybatis.xml</param-value> </context-param> <!-- 编码过滤器 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <async-supported>true</async-supported> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Spring监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 避免Spring内存溢出监听器 --> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <session-config> <session-timeout>600</session-timeout> </session-config> <!-- Spring MVC servlet --> <servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <!-- 此处能够能够配置成*.do,对应struts的后缀习惯 --> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>/index.jsp</welcome-file> </welcome-file-list> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> <url-pattern>*.css</url-pattern> <url-pattern>*.png</url-pattern> <url-pattern>/assets/*"</url-pattern> <url-pattern>/3rd/*</url-pattern> </servlet-mapping></web-app>业务代码电影首页@GetMapping(value = {"index",""})public ModelAndView index(ModelAndView mav, HttpSession session){ List<Movies> randomList=moviesService.randomMovies(); //预报电影 List<Movies> hotList=moviesService.findHotMovies(); //热门电影 List<Movies> newestList=moviesService.findNewestList(); //最新电影 List<Movies> indexNewestList=new ArrayList<>(); for(Movies movies:newestList){ List<MoviesType> moviesTypes=moviesTypeService.findListById(movies.getId()); movies.setMoviesTypes(moviesTypes); indexNewestList.add(movies); } List<Movies> recommendList; Person person=(Person) session.getAttribute("loginUser"); if(person!=null){ //如果登录,查看珍藏类型的电影 , recommendList=moviesService.findRecommendList(person.getId()); //电影举荐 }else{//如果没登录,查问热门的10个电影 recommendList=moviesService.findHotMovies(); } mav.addObject("randomList",randomList); mav.addObject("hotList",hotList); mav.addObject("newestList",newestList); mav.addObject("recommendList",recommendList); mav.setViewName("pc/index"); return mav;}//前端jsp<html lang="en"><head> <meta charset="UTF-8"> <title>程序帮,爱电影</title> <meta name="keywords" content=""> <meta name="description" content=""> <script src="${pageContext.request.contextPath}/assets/pc/js/jquery-1.11.3.min.js"></script> <script src="${pageContext.request.contextPath}/assets/pc/js/index.js"></script> <link rel="stylesheet" href="${pageContext.request.contextPath}/assets/pc/css/index.css"></head><body><jsp:include page="head.jsp"/><div class="gg">布告:如果你喜爱程序帮,爱电影,心愿你能把程序帮,爱电影推广给更多的敌人,多谢!</div><div class="out l"> <div class="hot"> ![](${pageContext.request.contextPath}/assets/pc/images/ribbon.png) </div> <ul class="img "> <li> <a href="# "> ![](${pageContext.request.contextPath}/assets/pc/images/1.jpg ) </a> </li> <li> <a href="# "> ![](${pageContext.request.contextPath}/assets/pc/images/2.jpg ) </a> </li> <li> <a href="# "> ![](${pageContext.request.contextPath}/assets/pc/images/3.jpg ) </a> </li> <li> <a href="# "> ![](${pageContext.request.contextPath}/assets/pc/images/4.jpg ) </a> </li> <li> <a href="# "> ![](${pageContext.request.contextPath}/assets/pc/images/5.jpg ) </a> </li> </ul> <ul class="num " > </ul> <div class="left btn "><</div> <div class="right btn right-btn">></div></div><div class="box-line"><%-- <span>随机电影资源</span>--%> <span>电影预报</span></div><div class="menu"> <div class="menu_item"> <c:forEach items="${randomList}" var="randoms"> <div class="menu_item_img"> <a href="${pageContext.request.contextPath}/details/${randoms.id}"> ![](${fn:substring(randoms.img, 0, fn:indexOf(randoms.img, ) ![](${fn:substring(randoms.img, fn:indexOf(randoms.img, ) </a> </div> </c:forEach> </div></div><main> <div class="main"> <div class="main_title"> <h3>最新电影</h3> <a href="">更多>></a> </div> <c:forEach items="${newestList}" var="newest"> <div class="main_item"> <a class="main_item_img" href="${pageContext.request.contextPath}/details/${newest.id}"> ![](${fn:substring(newest.img, 0, fn:indexOf(newest.img, ) ![](${pageContext.request.contextPath}/assets/pc/images/play-icon.png) <span class="cq">超清</span> </a> <div class="main_item_title"> <h1> <a href="#" target="_blank" title="${newest.name}">${newest.name}</a> <em> - ${newest.score}分</em> </h1> <div class="main_item_title_lei"> 类型: <c:forEach items="${newest.moviesTypes}" var="type" varStatus="index"> <c:if test="${index.index<=3}"> <a class="movietype" href="#">${type.typeName}</a> </c:if> </c:forEach> </div> </div> </div> </c:forEach> <div class="cl"></div> </div> <div class="right"> <div class="right_title"> <h3>热门电影</h3> </div> <c:forEach items="${hotList}" var="hot" varStatus="index" > <div class="list-group"> <a class="list-group-item" target="_blank" href="${pageContext.request.contextPath}/details/${hot.id}"> <span class="${index.index<3?'square-item-red':'square-item-blue'}">${index.index+1}</span> ${hot.name} </a> </div> </c:forEach> </div></main><div class="main3"> <div class="main3_title"> <h3>电影举荐</h3> <a href="">更多>></a> </div> <c:forEach items="${recommendList}" var="recommend" varStatus="index"> <c:if test="${index.index<10}"> <div class="main3_item"> <div class="main3_item_img"> <a href="#"> ![](${fn:substring(recommend.img, 0, fn:indexOf(recommend.img, ) </a> <span class="lg">蓝光</span> <div class="main3_item_title"> <h1> <a href="#" target="_blank" title="${recommend.name}">${recommend.name}</a> <em> - ${recommend.score}分</em> </h1> <div class="main3_item_title_lei"> 类型: <c:forEach items="${recommend.moviesTypes}" var="type" varStatus="index"> <c:if test="${index.index<=3}"> <a class="movietype" href="#">${type.typeName}</a> </c:if> </c:forEach> </div> </div> </div> </div> </c:if> </c:forEach></div></body></html>电影珍藏@ResponseBody@PostMapping(value = {"addCollection"})@ApiOperation(value = "增加珍藏",response = MyCollection.class)public Map addCollection( LikeMoviesDto likeMoviesDto){ Map map=ResponseMessage.success(); try{ MyCollection myCollection=new MyCollection(); BeanUtils.copyProperties(likeMoviesDto,myCollection); int result=myCollectionService.addCollection(myCollection); if(result==2){ myCollectionService.delCollection(myCollection); map=ResponseMessage.success("勾销珍藏胜利"); }else if(result==1){ Map data=new HashMap(); data.put("collectionId",myCollection.getId()); map=ResponseMessage.success("电影珍藏胜利"); map.put("data",data); }else{ map=ResponseMessage.fail("电影珍藏失败"); } }catch (Exception e){ e.printStackTrace(); map=ResponseMessage.fail("电影珍藏失败"); } return map;}//ajax申请function addCollection() { var user='${loginUser}'; if(null==user||user==''){ layer.msg('请先登录', {icon: 5}); }else{ var data={mId:${details.movies.id},uId:'${loginUser.id}'}; $.post('${pageContext.request.contextPath}/addCollection', data, function (data) { console.log(data); if (200 == data.returnCode) { layer.msg(data.returnMsg, {icon: 1, time: 1500}, function () { window.location.reload(); }); } else { layer.closeAll('loading'); layer.msg(data.returnMsg, {icon: 5}); } }, 'JSON'); }}我的项目后续其余ssh,springboot版本后续迭代更新,继续关注 ...

January 16, 2021 · 4 min · jiezi

关于jsp:jsp-elementui

导入<link rel="stylesheet" href="${webRoot}/plug-in/element-ui/css/index.css"> <link rel="stylesheet" href="${webRoot}/plug-in/element-ui/css/elementui-ext.css"> <script src="${webRoot}/plug-in/vue/vue.js"></script> <script src="${webRoot}/plug-in/vue/vue-resource.js"></script> <script src="${webRoot}/plug-in/element-ui/index.js"></script>不是规范的开发

January 14, 2021 · 1 min · jiezi

关于jsp:jspservlet实战酷炫博客聊天系统

我的项目介绍本我的项目应用jsp+servlet+mysql架构搭建可聊天的酷炫博客零碎。界面十分难看,除了登录注册集体核心批改外,博客还增加背景音乐,可在线交友聊天,发表动静,互相评论等,喜爱的博文还能增加珍藏。开发环境:jdk 8intellij ideatomcat 8mysql 5.7所用技术:jsp+servletjs+ajaxlayuijdbc+C3P0博客拜访地址http://localhost:8090/indexServlet我的项目目录构造 运行成果登录 首页 动静评论 关注列表 个人资料 聊天页面 外围代码:1.注册应用邮箱验证码 //邮件对象public class EmailModel { private String title;//题目 private String receiverEmail;//接管人邮箱 private String text;//发送内容 public static String register="欢送来到微博客n您的注册为:"; public static String registerTitle="注册验证码"; public static String findPwdTitle="找回明码:"; public static String findPwdText="找回明码验证码:";}// 邮件发送public class EmailUtils { private final static String authorizationCode="khdotvxxxxdba"; //受权码-本人设置 private final static String senderEmail ="1022287044@qq.com"; //发送人邮箱--测试邮箱 //发送邮件办法 public static int sendEmail(EmailModel emailModel){ try{ Properties props = new Properties(); // 开启debug调试 props.setProperty("mail.debug", "false"); // 发送服务器须要身份验证 props.setProperty("mail.smtp.auth", "true"); // 设置邮件服务器主机名 props.setProperty("mail.host", "smtp.qq.com"); // 发送邮件协定名称 props.setProperty("mail.transport.protocol", "smtp"); MailSSLSocketFactory sf = new MailSSLSocketFactory(); sf.setTrustAllHosts(true); props.put("mail.smtp.ssl.enable", "true"); props.put("mail.smtp.ssl.socketFactory", sf); Session session = Session.getInstance(props); Message msg = new MimeMessage(session); msg.setSubject(emailModel.getTitle());//题目 StringBuilder builder = new StringBuilder(); builder.append(emailModel.getText()); msg.setText(builder.toString()); msg.setFrom(new InternetAddress(senderEmail));//发送人的邮箱地址 Transport transport = session.getTransport(); //发送人的邮箱地址 //你的邮箱明码或者受权码 transport.connect("smtp.qq.com", senderEmail, authorizationCode); transport.sendMessage(msg, new Address[] { new InternetAddress(emailModel.getReceiverEmail()) });// 接管人的邮箱地址 transport.close(); return 1; }catch (Exception e){ e.printStackTrace(); return 0; } }}//注册及发送邮箱验证码public void doGet(HttpServletRequest request, HttpServletResponse response) { try{ PrintWriter printWriter=response.getWriter(); HttpSession session=request.getSession(); String action = request.getParameter("action"); String userName=request.getParameter("userName"); String password=request.getParameter("password"); if("sendEmail".equals(action)){ //发送验证码 String receiverEmail=request.getParameter("receiverEmail"); String type=request.getParameter("type"); String authCode=RandomUtil.randomNumbers(4); EmailModel emailModel=new EmailModel(); if("register".equalsIgnoreCase(type)){ //注册 User search=new User(); search.setUserName(receiverEmail); search=userService.getUser(search); if(null!=search){ printWriter.println("2"); return; }else{ emailModel.setTitle(EmailModel.registerTitle); emailModel.setText(EmailModel.register+authCode); } }else{ //找回明码 emailModel.setTitle(EmailModel.findPwdTitle); emailModel.setText(EmailModel.findPwdText+authCode); } System.out.println("邮箱验证码:"+authCode); emailModel.setReceiverEmail(receiverEmail); int result= EmailUtils.sendEmail(emailModel); session.setAttribute(receiverEmail+"#EmailCode",authCode);//注册验证码 printWriter.println(result); }else if("doRegister".equals(action)){ //注册验证 String authCode=request.getParameter("authCode");//验证码 String sessionCode=(String)session.getAttribute(userName+"#EmailCode");//注册验证码 if(null==sessionCode){ printWriter.println("3"); //验证码为空,请先获取邮箱验证码 }else if(!sessionCode.equals(authCode)){ printWriter.println("2"); //验证码谬误 }else{ User user=new User(); user.setUserName(userName); user.setNickName(userName); user.setPassword(password); int result=userService.addUser(user); printWriter.println(result); //验证胜利 } } }catch (Exception e){ e.printStackTrace(); return ; }}2.上传头像 ...

December 26, 2020 · 3 min · jiezi

关于jsp:jspservlet搭建在线投票问卷系统

点赞再看,养成习惯 程序帮QQ:1022287044 开发环境筹备:jdk1.8tomcat8mysql5.7intellij IDEA零碎采纳技术:jsp+ servlet mvc三层架构模式jdbcjQuery+ajaxECharts 4.3.0我的项目介绍用户端 用户端能够查看问卷列表并参加问卷调查查看集体参加的调查报告以及整个问卷状况治理端 问卷的新增和保护用户信息保护我的项目设计 运行成果登录 增加问卷 问卷投票列表 投票详情 数据库表 代码构造截图 要害代码:1.增加问卷: public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { String questionTitle = request.getParameter("questionTitle"); //问卷题目 String qId = request.getParameter("qId"); //问卷id Integer ops =Integer.valueOf(request.getParameter("ops"));//具体几组 String doType=request.getParameter("doType"); //操作类型 User user=(User)request.getSession().getAttribute(User.SESSIONNAME); SubjectService subjectService=new SubjectServiceImpl(); List<Subject> subjects=new ArrayList<>(); //问题列表 Question question=new Question(); question.setTitle(questionTitle); if("add".equalsIgnoreCase(doType)){ //如果批改增加id if(null!=user){//用户对象不为空,保留值 question.setUserId(user.getId()); } }else{ question.setId(Integer.valueOf(qId)); } String title=""; for(int i=0;i<ops;i++){ int number = Integer.parseInt(request.getParameter("number"+i)); String[] os = request.getParameterValues("options"+i); String[] osIds = request.getParameterValues("optionsIds"+i);//选项id title=request.getParameter("title"+i);//问题题目 String titleId=request.getParameter("titleId"+i);//问题id Subject subject = new Subject(); subject.setOrderId(i); subject.setTitle(title); subject.setNumber(number); if(null!=titleId&&!"".equalsIgnoreCase(titleId)){//设置问题id subject.setId(Integer.valueOf(titleId)); } for(int i1=0;i1<os.length;i1++){ Option op = new Option(); op.setContent(os[i1]); if("modify".equalsIgnoreCase(doType)){ //如果批改增加id op.setId(Integer.valueOf(osIds[i1])); } subject.getOptions().add(op); } try { long startTime=new Date().getTime(); subject.setStartTime(startTime); subject.setEndTime(startTime+1*24*60*60*1000); subject.setMaster(user); subjects.add(subject); } catch (ReTryException e) { HttpSession session = request.getSession(); session.setAttribute("subject", subject); session.setAttribute("message", e.getMessage()); response.sendRedirect(request.getContextPath() + "/m/add"); } catch (Exception ex) { throw new RuntimeException(ex); } } try{ if("add".equalsIgnoreCase(doType)){//增加 subjectService.add(question,subjects); }else{//批改 subjectService.modify(question,subjects); } }catch (Exception e){ e.printStackTrace(); } if(null!=user&&user.getRole().equalsIgnoreCase("user")){ response.sendRedirect(request.getContextPath() + "/list?action=myRelease");//用户查看本人的公布 }else{ response.sendRedirect(request.getContextPath() + "/list?action=index"); } }2.批改问卷信息 ...

December 22, 2020 · 3 min · jiezi

关于jsp:JSP和JSTL

JSPJSP的根底语法简介 JSP:Java Server Page SUN 公司提供的动静网页编程技术,是 Java Web 服务器端的动静资源。 它相比 html 而言,html 只能为用户提供静态数据,而 Jsp 技术容许在页面中嵌套 java 代码,为用户提供动态数据。 相比 servlet 而言,servlet 很难对数据进行排版,而 jsp 除了能够用 java 代码产生动态数据的同时,也很容易对数据进行排版。 不论是 JSP 还是 Servlet,尽管都能够用于开发动静 web 资源。但因为这 2 门技术各自的特点,在长期的软件实际中,人们逐步把 servlet 作为 web 利用中的控制器组件来应用, 而把 JSP 技术作为数据显示模板来应用。 其实 Jsp 就是一个 Servlet,当咱们第一次拜访 Jsp 的时候,Jsp 引擎都会将这个 Jsp 翻译 成一个 Servlet,这个文件寄存在tomcat(源码目录) 中的 work 目录中。 筹备工作配置IDEA 这一步不是必须的,当然因为 编辑器中有些默认的配置项咱们感觉不是很完满,比方"编码格局"、页面模板等。咱们能够在新建 JSP 页面之前就先批改为咱们须要的。 1.抉择"File" —> “Settings…” ...

November 27, 2020 · 7 min · jiezi

关于jsp:JSPELJSTL

JSP介绍JSP和Servlet都是由SUN公司提供的一门动静web资源开发技术。JSP看起来像一个HTML,和HTML不同的是,JSP中能够书写Java代码,能够通过Java代码显示动态数据。JSP实质上就是一个Servlet。 JSP的由来1.Servlet实质是一段Java程序,适宜解决业务逻辑,不适宜向外输入一个(残缺的复合标准的)html网页。2.HTML就是一个页面的开发技术,适宜作为网页进行输入,然而html是一个动态Web资源开发技术,无奈展现动态数据(HTML+AJAX)。3.JSP也是一个页面的开发技术,能够输入html网页,并且JSP能够通过Java代码展现动态数据。JSP的呈现,既解决了Servlet不适宜输入网页的问题,也解决了HTML无奈展现动态数据的问题 为什么说JSP实质是一个Servlet? 在JSP第一次被拜访时,会翻译成一个Servlet程序。拜访JSP后看到的html网页,其实是翻译后的Servlet执行的后果。(也就是说,拜访JSP后看到的网页,是JSP翻译后的Servlet输入到浏览器的。) JSP的执行流程 当浏览器申请服务器中的某一个JSP文件(例如:localhost:8080/day11-jsp/test.jsp),服务器会依据申请资源的门路去寻找该文件:如果找到了,JSP翻译引擎会将JSP翻译成一个Servlet程序(JSP----> xxx.java----> xxx.class),而后Servlet程序再执行,执行的后果是向浏览器输入一个HTML网页!如果没有找到,服务器将会响应一个404页面,告诉浏览器申请的资源不存在。JSP表达式格局:<%= 常量、变量、表达式 %>作用:计算表达式的后果,将后果输入到浏览器中,由浏览器负责解析并显示。 <%= "Hello JSP..." %><% String name = "林青霞"; %><%= name %><%= 100+123 %><%= Math.random() %>留神:JSP表达式中能够书写合乎Java语法的代码,然而不能写Java语句(外部不能写分号;)JSP脚本片段格局:<% 若干Java语句 %> <!-- 在页面上输入5行"hello JSP" --><% for(int i=0; i<5; i++){ out.write("Hello JSP...<br/>"); }%>JSP正文格局:<%-- JSP正文内容 --%>面试题:考查JSP中的JSP正文、Java正文、html正文 <%-- <% out.write( "aaaaa<br/>" ); %> --%><% //out.write( "bbbbb<br/>" ); %><!-- <% out.write( "ccccc<br/>" ); %> -->问题:(1)下面输入的三行内容,在拜访时,会显示哪一行内容? 第一行被JSP正文给正文了,JSP正文的内容不会参加翻译,也不会执行,更不会发送给浏览器,也不会在浏览器上显示。 第二行被Java正文给正文了,放在脚本片段中的内容会参加翻译,会将其中的Java代码复制到翻译后的Servlet中,但因为代码被正文了,所以不会执行,也不会发送给浏览器,更不会在浏览器上显示。 第三行被html正文给正文了,html正文在JSP中是模板元素,正文自身会发送给浏览器,正文中的脚本片段会参加翻译,其中的java代码也会执行,也会将内容(ccccc)发送给浏览器,但因为发送到浏览器后的ccccc被html正文包裹,因而也不会显示在浏览器上。 (2)下面输入的三行内容,哪一行会发送到浏览器中?(不论是否显示) 其中第三行内容会发送到浏览器中,但不会显示,因为前后有html正文。 JSP指令指令的格局:<%@ 指令名称 若干属性申明... %> ...

November 11, 2020 · 1 min · jiezi

关于jsp:SAP-Hybris-Commerce的JSP-tag和SAP-BSP-tag的比较

Recently I am studying Hybrid Commerce and try to learn how the home page of Hybris storefront is implemented. I try the approach introduced in my blog Technical data for Hybris Commerce UI – how to find the name of JSP page for a given UIand find the JSP file which implements the home page: hybrisbinext-templateyacceleratorstorefrontwebwebrootWEB-INFviewsresponsivepageslayoutlandingLayout2Page.jsp When I debug this file I find there are lots of usage of tag <jsp:attribute> as displayed below. ...

September 1, 2020 · 3 min · jiezi

关于jsp:SpringBoot整合动态web资源

在之前的文章中,介绍过springboot整合web资源,然而那时应用的是thymelef,整合的是html动态web资源,然而当初尽管较新的我的项目都是应用html,然而仍旧有一部分应用jsp来编辑页面的,所以来说一下整合jsp动静web资源. 创立springboot war包我的项目 因为springboot中没有webapp目录,所以咱们须要在main目录下新建webapp目录-->WEB-INF目录-->在其中创立jsp页面 编辑pom.xml文件,增加jar包依赖<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jt</groupId> <artifactId>springboot_jsp</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>demo</name> <description>Demo project for Spring Boot</description> <!--parent标签作用: 定义了SpringBoot中所有关联我的项目的版本号信息.--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</java.version> <!--我的项目打包时,跳过测试类打包--> <skipTests>true</skipTests> </properties> <!--开箱即用:SpringBoot我的项目只须要引入大量的jar包及配置,即可领有其性能. spring-boot-starter 领有开箱即用的能力. maven我的项目中依赖具备传递性. A 依赖 B 依赖 C我的项目 导入A bc会主动依赖 --> <dependencies> <!--间接依赖web springMVC配置--> <dependency> <groupId>org.springframework.boot</groupId> <!--springBoot-start SpringBoot启动项 --> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--SpringBoot重构了测试形式 能够在测试类中 间接引入依赖对象--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!--反对热部署 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!--引入插件lombok 主动的set/get/构造方法插件 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--引入数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!--springBoot数据库连贯 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!--spring整合mybatis-plus 只导入MP包,删除mybatis包 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.2.0</version> </dependency> <!--springBoot整合JSP增加依赖 --> <!--servlet依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <!--jstl依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <!--使jsp页面失效 --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> </dependencies> <!--在我的项目打包部署时失效,如果不增加build,则程序公布时不然会报 我的项目中没有main办法. --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>批改yml配置文件,增加页面门路前缀,以及类型后缀spring: #引入mvn配置 mvc: view: prefix: /WEB-INF/ # /默认代表根目录 src/main/webapp suffix: .jsp

August 28, 2020 · 1 min · jiezi

关于jsp:JSP转载3y

什么是JSPJSP全名为Java Server Pages,java服务器页面。JSP是一种基于文本的程序,其特点就是HTML和Java代码独特存在! 为什么须要JSPJSP是为了简化Servlet的工作呈现的替代品,Servlet输入HTML十分艰难,JSP就是代替Servlet输入HTML的。 简略应用一下JSP在idea下生成一个JSP,咱们来看一下JSP长什么样子 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>简略应用JSP</title> </head> <body> </body> </html>看起来就像一个HTML页面,后面也说了:JSP的特点就是HTML和Java代码独特存在咱们向浏览器输入一句HelloWorld,至于<%%>这个货色,我先不解释! <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>简略应用JSP</title> </head> <body> <% String s = "HelloWorld"; out.println(s); %> </body> </html> JSP的工作原理在Tomcat博客中我提到过:Tomcat拜访任何的资源都是在拜访Servlet!,当然了,JSP也不例外!JSP自身就是一种Servlet。为什么我说JSP自身就是一种Servlet呢?其实JSP在第一次被拜访的时候会被编译为HttpJspPage类(该类是HttpServlet的一个子类)方才我简略应用了一下JSP,它被编译成了这么一个Servlet:package org.apache.jsp;import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.jsp.*;import java.util.Date;public final class _1_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory(); private static java.util.List<String> _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.List<String> getDependants() { return _jspx_dependants; } public void _jspInit() { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); } public void _jspDestroy() { } public void _jspService(final HttpServletRequest request, final HttpServletResponse response) throws java.io.IOException, ServletException { final PageContext pageContext; HttpSession session = null; final ServletContext application; final ServletConfig config; JspWriter out = null; final Object page = this; JspWriter _jspx_out = null; PageContext _jspx_page_context = null; try { response.setContentType("text/html;charset=UTF-8"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("\r\n"); out.write("\r\n"); out.write("<html>\r\n"); out.write("<head>\r\n"); out.write(" <title>简略应用JSP</title>\r\n"); out.write("</head>\r\n"); out.write("<body>\r\n"); String s = "HelloWorda"; out.println(s); out.write("\r\n"); out.write("</body>\r\n"); out.write("</html>\r\n"); } catch (Throwable t) { if (!(t instanceof SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { out.clearBuffer(); } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } }}编译过程是这样子的:浏览器第一次申请1.jsp时,Tomcat会将1.jsp转化成1_jsp.java这么一个类,并将该文件编译成class文件。编译结束后再运行class文件来响应浏览器的申请。当前拜访1.jsp就不再从新编译jsp文件了,间接调用class文件来响应浏览器。当然了,如果Tomcat检测到JSP页面改变了的话,会从新编译的。既然JSP是一个Servlet,那JSP页面中的HTML排版标签是怎么样被发送到浏览器的?咱们来看下下面1_jsp.java的源码就晓得了。原来就是用write()进来的罢了。说到底,JSP就是封装了Servlet的java程序罢了。 out.write("\r\n"); out.write("\r\n"); out.write("<html>\r\n"); out.write("<head>\r\n"); out.write(" <title>简略应用JSP</title>\r\n"); out.write("</head>\r\n"); out.write("<body>\r\n");有人可能也会问:JSP页面的代码服务器是怎么执行的?再看回1_jsp.java文件,java代码就间接在类中的service()中。 String s = "HelloWorda"; out.println(s);JSP比Servlet更不便更简略的一个重要起因就是:内置了9个对象!内置对象有:out、session、response、request、config、page、application、pageContext、exception,这几个内置对象不在这里讲。当初先晓得一下即可!*JSP生命周期JSP也是Servlet,运行时只有一个实例,JSP初始化和销毁时也会调用Servlet的init()和destroy()办法。另外,JSP还有本人初始化和销毁的办法 ...

August 18, 2020 · 11 min · jiezi

JSPSSHMysqlDBCP实现的租车系统

项目简介项目来源于:https://github.com/1462656075/car本系统是基于JSP+SSH+Mysql+DBCP实现的租车系统。在当代开发中,SSH的使用已经逐渐被SSM取代,但不代表我们不需要学习SSH,该系统简单,但功能齐全可以作为SSH框架初学者的入门项目。 难度等级:中等 技术栈编辑器Eclipse Version: 2019-12 (4.14.0) 前端技术基础:html+css+JavaScript 框架:JQuery+Bootstrap+Apache ECharts 后端技术SSH(struts2+spring+hibernate) 数据库:mysql 5.7.27(个人测试使用) 数据库连接池:DBCP jdk版本:1.8.0_181(个人测试使用) tomcat版本:7.0.47(个人测试使用) 本地运行Eclipse环境准备1.eclipse新增jdk 2.eclipse新增tomcat 导入项目若有疑惑可查看视频版本。1.下载zip直接解压或安装git后执行克隆命令  git clone https://github.com/1462656075/car若下载过慢可将github仓库复制到gitee上。 查看视频 2.使用eclipse导入项目,配置jdk、tomcat和所需jar包。项目所依赖jar包在WebContent/WEB-INF/lib文件夹下。 3.打开Navicat For Mysql,创建cars数据库,并运行cars.sql文件。 4.修改config/jdbc.properties中数据库相关的内容。 5.将carmyupload文件夹发布到tomcat中,发布路径为/upload。若不配置,则项目中图片无法访问。 6.修改发布配置,去掉项目名称,否则无法正常访问。 7.发布到tomcat中,具体访问链接看tomcat配置,若未修改则http://localhost:8080/login_index.do?role=1为首页。默认账号:zs 默认密码:123 http://localhost:8080/login_login.do?role=2为后台管理登录页初始账号:admin 初始密码:123 注意该项目未声明mysql、jdk、tomcat使用版本,以上版本号均为个人测试使用版本。注意修改config/jdbc.properties中数据库相关的内容。将carmyupload文件夹发布到tomcat中,发布路径为/upload。若不配置,则项目中图片无法访问。项目截图 声明该项目收集于github,本人只是代为说明使用技术、注意点及启动方式,帮助大家进行学习交流。若通过github地址无法下载该项目或无法正常运行,可私信我,本人免费协助。推荐阅读JSP+Servlet+JDBC+DBCP2实现在线购书系统JSP+Servlet+JDBC实现的shine网上书城JSP+Servlet+JDBC实现的云端汽修后台管理系统JSP+Servlet+JDBC实现的学生信息管理系统JSP+Servlet+C3P0+Mysql实现的YCU movies电影网站JSP+Servlet+C3P0+Mysql实现的图书馆管理系统本篇已收录于个人GitHub仓库https://github.com/coderzcr/JavaWeb-Project-Source-Share,欢迎Star。

June 9, 2020 · 1 min · jiezi

JSPStructsJDBCmysql实现的诚欣电子商城

项目简介项目来源于:https://github.com/SuperiorNature/Java-Enterprise-electronic-mall本系统是基于JSP+Structs+JDBC+Mysql实现的电子商城系统。界面和技术都比较过时,适合structs入门者。 难度等级:中等 技术栈编辑器Eclipse Version: 2020-03 (4.15.0) 前端技术基础:html+css+JavaScript 框架:无,纯手写。 后端技术模板引擎:JSP 控制器:structs 数据库:mysql 5.7.27(个人测试使用) jdk版本:1.8.0_251(个人测试使用) tomcat版本:7.0.47(个人测试使用) 本地运行Eclipse环境准备1.eclipse新增jdk 2.eclipse新增tomcat 导入项目若有疑惑可查看视频版本。1.下载zip直接解压或安装git后执行克隆命令。 git clone https://github.com/SuperiorNature/Java-Enterprise-electronic-mall.git若下载过慢可将github仓库复制到gitee上。 查看视频2.使用eclipse导入项目,配置jdk、tomcat和所需jar包。项目所依赖jar包在WebContent/WEB-INF/lib文件夹下。 3.打开Navicat For Mysql,创建db_shopping数据库,并运行db_shopping.sql文件。 4.修改com.wy.tool.JDBConnection中数据库相关的内容。 5.发布到tomcat中,具体访问链接看tomcat配置,若未修改则http://localhost:8080/Shopping/为首页。 http://localhost:8080/Shopping/bg-land.jsp为后台管理登录页。 管理员初始账号:Tsoft 系统管理员初始密码:111 注意该项目未声明mysql、jdk、tomcat使用版本,以上版本号均为个人测试使用版本。注意修改com.wy.tool.JDBConnection中数据库相关的内容。项目截图 声明该项目收集于gitee,本人只是代为说明使用技术、注意点及启动方式,帮助大家进行学习交流。若通过gitee地址无法下载该项目或无法正常运行,可私信我,本人免费协助。推荐阅读JSP+Servlet+JDBC+DBCP2实现在线购书系统JSP+Servlet+JDBC实现的shine网上书城JSP+Servlet+JDBC实现的云端汽修后台管理系统JSP+Servlet+JDBC实现的学生信息管理系统JSP+Servlet+C3P0+Mysql实现的YCU movies电影网站JSP+Servlet+C3P0+Mysql实现的图书馆管理系统本篇已收录于个人GitHub仓库https://github.com/coderzcr/JavaWeb-Project-Source-Share,欢迎Star。

June 8, 2020 · 1 min · jiezi

Spring-FORM-标签库

Spring FORM标签库Spring MVC提供了一个JSP标签库(Spring Form),使将表单元素绑定到Model 数据变得更加容易。Spring Framework 提供了一些标签,用于显示 错误,设置主题和输出国际化消息。 使用Spring Form标签库的语法需要在jsp文件头部加上: <%@taglib uri="http://www.springframework.org/tags/form" prefix="form">本示例中使用的表单标签呈现HTML “form” 标签,并向内部标签公开绑定路径以进行绑定。使用绑定值呈现类型为“text”的HTML“input”标记。在HTML'span'标签中呈现字段错误。使用绑定值呈现类型为“ password”的HTML “input”标签。呈现类型为“radio”的HTML“ input”标签。呈现HTML“select”元素。支持数据绑定到所选选项。呈现单个HTML“option”。根据绑定值适当设置“selected”。呈现HTML“textarea”。呈现类型为“checkbox”的HTML“input”标签。简单注册表单示例1.修改web.xml以配置Dispatcher Servlet。web.xml <?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> <session-config> <session-timeout> 30 </session-timeout> </session-config> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>创建一个dispatcher-servlet.xml文件,其中包含所有用于处理用户请求的配置bean,它处理用户请求并将其分派到各个控制器。dispatcher-servlet.xml <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/> <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="urlMap"><map><entry key="/index.html"><ref bean="registrationController"/></entry></map></property> </bean><bean id="registrationValidator" class="registrationValidator"/><bean id="registrationController" class="RegistrationFormController"><property name="sessionForm"><value>false</value></property><property name="commandName" value="registration"></property><property name="commandClass" value="Registration"></property><property name="validator"><ref bean="registrationValidator"/></property><property name="formView"><value>index</value></property><property name="successView"><value>success</value></property></bean><bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="messages"/> </bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" /></beans>3.创建一个Jsp文件以从用户index.jsp接收输入,该文件包含带有Spring Form标签的所有表单字段。 index.jsp ...

October 6, 2019 · 3 min · jiezi

JSP-点击量统计

详细JSP课程:阿里云大学——开发者课堂有时候我们需要知道某个页面被访问的次数,这时我们就需要在页面上添加页面统计器,页面访问的统计一般在用户第一次载入时累加该页面的访问数上。要实现一个计数器,您可以利用应用程序隐式对象和相关方法getAttribute()和setAttribute()来实现。这个对象表示JSP页面的整个生命周期中。当JSP页面初始化时创建此对象,当JSP页面调用jspDestroy()时删除该对象。以下是在应用中创建变量的语法: application.setAttribute(String Key, Object Value);您可以使用上述方法来设置一个计数器变量及更新该变量的值。读取该变量的方法如下: application.getAttribute(String Key);在页面每次被访问时,你可以读取计数器的当前值,并递增1,然后重新设置,在下一个用户访问时就将新的值显示在页面上。 实例演示该实例将介绍如何使用JSP来计算特定页面访问的总人数。如果你要计算你网站使用页面的总点击量,那么你就必须将该代码放在所有的JSP页面上。 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ page import="java.io.*,java.util.*" %><html><html><head><title>访问量统计</title></head><body><% Integer hitsCount = (Integer)application.getAttribute("hitCounter"); if( hitsCount ==null || hitsCount == 0 ){ /* 第一次访问 */ out.println("欢迎访问阿里云大学!"); hitsCount = 1; }else{ /* 返回访问值 */ out.println("欢迎再次访问阿里云大学!"); hitsCount += 1; } application.setAttribute("hitCounter", hitsCount);%><p>页面访问量为: <%= hitsCount%></p></body></html>现在我们将上面的代码放置于main.jsp文件上,并访问http://localhost:8080/testjsp/main.jsp文件。你会看到页面会生成个计数器,在我们每次刷新页面时,计数器都会发生变化(每次刷新增加1)。 复位计数器使用以上方法,在 web 服务器重启后,计数器会被复位为 0,即前面保留的数据都会消失,你可以使用以下几种方式解决该问题:• 在数据库中定义一个用于统计网页访问量的数据表 count,字段为 hitcount,hitcount 默认值为0,将统计数据写入到数据表中。• 在每次访问时我们读取表中 hitcount 字段。 • 每次访问时让 hitcount 自增 1。• 在页面上显示新的 hitcount 值作为页面的访问量。 • 如果你需要统计每个页面的访问量,你可以使用以上逻辑将代码添加到所有页面上。 ...

May 31, 2019 · 1 min · jiezi

jsp4

读取所有表单参数 以下我们将使用 HttpServletRequest 的 getParameterNames() 来读取所有表单参数,该方法可以取得所有变量的名称,该方法返回一个枚举。一旦我们有了一个 Enumeration(枚举),我们就可以调用 hasMoreElements() 方法来确定是否还有元素,以及使用nextElement()方法来获得每个参数的名称。 jsp代码如下: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ page import="java.io.*,java.util.*" %><!DOCTYPE html><html><head><meta charset="utf-8"><title>hqh</title></head><body><h1>读取所有表单参数</h1><table width="100%" border="1" align="center"><tr bgcolor="#949494"><th>参数名</th><th>参数值</th></tr><% Enumeration paramNames = request.getParameterNames(); while(paramNames.hasMoreElements()) { String paramName = (String)paramNames.nextElement(); out.print("<tr><td>" + paramName + "</td>\n"); String paramValue = request.getParameter(paramName); out.println("<td> " + paramValue + "</td></tr>\n"); }%></table></body></html>html代码如下: <!DOCTYPE html><html><head><meta charset="utf-8"><title>hqh</title></head><body><form action="NewFile.jsp" method="POST" target="_blank"><input type="checkbox" name="google" checked="checked" /> Google<input type="checkbox" name="baidu" /> 百度<input type="checkbox" name="taobao" checked="checked" /> 淘宝<input type="submit" value="选择网站" /></form></body></html>通过访问 http://localhost:8080/tt2/test.html 提交表单数据到 jsp 文件中得到以下结果 再来回顾一下表单处理的两种函数: 一、GET方法 GET方法发送添加到页面请求的编码用户信息。页面和编码信息是被符号?分开的。 GET方法是从浏览器向Web服务器传递信息的默认的方法,它产生一个长字符串出现在浏览器的位置框中。如果要把密码或其他敏感信息传递到服务器,那么不要使用 GET 方法。 GET方法有大小限制:在请求字符串中只可以有1024个字符(但这个值可以通过配置来加大)。 这些信息是通过使用QUERY_STRING标题传递的,并将通过QUERY_STRING环境变量被接收,该环境变量可以使用请求对象的getQueryString()方法和getParameter()方法处理。 二、POST方法 通常情况下,将信息传递给后端程序的更可靠的方法是POST方法。 ...

May 12, 2019 · 1 min · jiezi

jsp3

使用表单的 GET 方法实例 在相同文件夹下创建test.html一个HTML表单,再通过GET方法将客户端数据提交 到 main.jsp 文件中/ <!DOCTYPE html><html><head><meta charset="utf-8"><title>hqh</title></head><body><form action="main.jsp" method="GET">站点名: <input type="text" name="name"><br />网址: <input type="text" name="url" /><input type="submit" value="提交" /></form></body></html>填入信息 调用成功。 使用表单的 POST 方法实例 其中对应的test文件中应该修改 <form action="NewFile.jsp" method=POST">jsp文件代码 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ page import="java.io.*,java.util.*" %><!DOCTYPE html><html><head><meta charset="utf-8"><title>hqh</title></head><body><h1>使用 POST 方法读取数据</h1><ul><li><p><b>站点名:</b><%String name = new String((request.getParameter("name")).getBytes("ISO-8859-1"),"UTF-8");%> <%=name%></p></li><li><p><b>网址:</b> <%= request.getParameter("url")%></p></li></ul></body></html>这句代码可以用来解决中文乱码 String name = new String((request.getParameter("name")).getBytes("ISO-8859-1"),"UTF-8"); 传递 Checkbox 数据到JSP程序 与上面的方法不同,这里可以调用复选框来传输信息 jsp代码: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ page import="java.io.*,java.util.*" %><!DOCTYPE html><html><head><meta charset="utf-8"><title>hqh</title></head><body><h1>从复选框中读取数据</h1><ul><li><p><b>是否选择1:</b> <%= request.getParameter("1")%></p></li><li><p><b>是否选择2:</b> <%= request.getParameter("2")%></p></li><li><p><b>是否选择3:</b> <%= request.getParameter("3")%></p></li></ul></body></html>test.html代码 <!DOCTYPE html><html><head><meta charset="utf-8"><title>hqh</title></head><body><form action="NewFile.jsp" method="POST" target="_blank"><input type="checkbox" name="1" checked="checked" /> 1<input type="checkbox" name="2" /> 2<input type="checkbox" name="3" checked="checked" /> 3<input type="submit" value="choose" /></form></body></html> ...

April 28, 2019 · 1 min · jiezi

jsp_2

当浏览器请求一个网页时,它会向网络服务器发送一系列不能被直接读取的信息,因为这些信息是作为HTTP信息头的一部分来传送的。我们便可以通过http协议获得更多的信息。 而request对象是javax.servlet.http.HttpServletRequest类的实例。每当客户端请求一个页面时,JSP引擎就会产生一个新的对象来代表这个请求。 下面这个例子使用HttpServletRequest类的getHeaderNames()方法来读取HTTP信息头。 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ page import="java.io.*,java.util.*" %><!DOCTYPE html><html><head><meta charset="utf-8"><title>hqh</title></head><body><h2>HTTP 头部请求实例</h2><table width="100%" border="1" align="center"> <%-- table表格 --%><tr bgcolor="#949494"> <%--定义背景色--%><th>Header Name</th><th>Header Value(s)</th> <%-- 表格标题 --%></tr><% Enumeration headerNames = request.getHeaderNames(); //返回所有HTTP头的名称集合 while(headerNames.hasMoreElements()) { //获取Enumeration对象后,遍历Enumeration对象 String paramName = (String)headerNames.nextElement(); out.print("<tr><td>" + paramName + "</td>\n"); String paramValue = request.getHeader(paramName); //返回paramName指定的信息头,也就是对应的值 out.println("<td> " + paramValue + "</td></tr>\n"); }%></table></body></html> Enumeration getAttributeNames()(返回request对象的所有属性名称的集合),Enumeration getParameterNames()(返回请求中所有参数的集合)在尝试这两个对应的方法时没有输出有效的信息。可能是信息不足,才没有输出。 while(headerNames.hasMoreElements()) { String paramName = (String)headerNames.nextElement(); out.print("<tr><td>" + paramName + "</td>\n"); String paramValue = request.getParameter(paramName); out.println("<td> " + paramValue + "</td></tr>\n"); }for(Enumeration e = request.getAttributeNames(); e.hasMoreElements();) { Object o = e.nextElement(); out.println((String) o + " : " + request.getAttribute((String) o) + " <br><hr> " ); } 同样的服务器在接收到客户端的信息后,会传输信息到客户端上。response 对象是 javax.servlet.http.HttpServletResponse 类的一个实例。就像服务器会创建request对象一样,它也会创建一个客户端响应。 ...

April 21, 2019 · 1 min · jiezi

jsp_1

看了些spring的书,还是看不懂,感觉自己后端的知识还是十分的薄弱的,于是打算从简单一些的jsp开始。<%@ page language=“java” contentType=“text/html; charset=UTF-8” pageEncoding=“UTF-8”%><!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv=“Content-Type” content=“text/html; charset=UTF-8”><title>hqh</title></head><body><% out.println(“第一个网页”);%></body></html>这样一个简单的网页就制作好了,在默认代码上改的。其中嵌入java语句是加入在<% %>里例如: <% out.println(“Your IP address is " + request.getRemoteAddr()); %>同时嵌入jsp表达式:今天的日期是: <%= (new java.util.Date()).toLocaleString()%>,其中语句部分以string形式呈现。加入变量,嵌套一些程序中常见的循环语句<%! int fontSize=0; %> //声明变量引用<jsp:include>动作元素 ,将另一网页插入当前网页:<jsp:include page=“NewFile1.jsp” flush=“true” />flush是布尔属性,定义在包含资源前是否刷新缓存区。jsp:useBean 动作用来加载一个将在JSP页面中使用的JavaBean。jsp:setProperty用来设置已经实例化的Bean对象的属性。jsp:getProperty动作提取指定Bean属性的值,转换成字符串,然后输出。<h2>Jsp 使用 JavaBean 实例</h2><jsp:useBean id=“test” class=“talk.b” /> <jsp:setProperty name=“test” property=“message” value=“javabean” /> <p>输出信息….</p> <jsp:getProperty name=“test” property=“message” />这里出错最多,开始以为是直接放java文件,但是询问大佬后知道是放class文件,编译java文件发现没有main入口,所以用cmd命令行编译,后放入class后发现路径有问题,反正折腾了很久弄出了网页对应了一下模板代码<jsp:useBean id=“name” class=“package.class” /><jsp:useBean id=“myName” … />…<jsp:setProperty name=“myName” property=“someProperty” …/><jsp:useBean id=“myName” … />…<jsp:getProperty name=“myName” property=“someProperty” …/> ...

April 14, 2019 · 1 min · jiezi

Java动态追踪技术探究

引子在遥远的希艾斯星球爪哇国塞沃城中,两名年轻的程序员正在为一件事情苦恼,程序出问题了,一时看不出问题出在哪里,于是有了以下对话:“Debug一下吧。”“线上机器,没开Debug端口。”“看日志,看看请求值和返回值分别是什么?”“那段代码没打印日志。”“改代码,加日志,重新发布一次。”“怀疑是线程池的问题,重启会破坏现场。”长达几十秒的沉默之后:“据说,排查问题的最高境界,就是只通过Review代码来发现问题。”比几十秒长几十倍的沉默之后:“我轮询了那段代码一十七遍之后,终于得出一个结论。”“结论是?”“我还没到达只通过Review代码就能发现问题的至高境界。”从JSP说起对于大多数Java程序员来说,早期的时候,都会接触到一个叫做JSP(Java Server Pages)的技术。虽然这种技术,在前后端代码分离、前后端逻辑分离、前后端组织架构分离的今天来看,已经过时了,但是其中还是有一些有意思的东西,值得拿出来说一说。当时刚刚处于Java入门时期的我们,大多数精力似乎都放在了JSP的页面展示效果上了:“这个表格显示的行数不对”“原来是for循环写的有问题,改一下,刷新页面再试一遍”“嗯,好了,表格显示没问题了,但是,登录人的姓名没取到啊,是不是Sesstion获取有问题?”“有可能,我再改一下,一会儿再刷新试试”……在一遍一遍修改代码刷新浏览器页面重试的时候,我们自己也许并没有注意到一件很酷的事情:我们修改完代码,居然只是简单地刷新一遍浏览器页面,修改就生效了,整个过程并没有重启JVM。按照我们的常识,Java程序一般都是在启动时加载类文件,如果都像JSP这样修改完代码,不用重启就生效的话,那文章开头的问题就可以解决了啊:Java文件中加一段日志打印的代码,不重启就生效,既不破坏现场,又可以定位问题。忍不住试一试:修改、编译、替换class文件。额,不行,新改的代码并没有生效。那为什么偏偏JSP可以呢?让我们先来看看JSP的运行原理。当我们打开浏览器,请求访问一个JSP文件的时候,整个过程是这样的:JSP文件修改过后,之所以能及时生效,是因为Web容器(Tomcat)会检查请求的JSP文件是否被更改过。如果发生过更改,那么就将JSP文件重新解析翻译成一个新的Sevlet类,并加载到JVM中。之后的请求,都会由这个新的Servet来处理。这里有个问题,根据Java的类加载机制,在同一个ClassLoader中,类是不允许重复的。为了绕开这个限制,Web容器每次都会创建一个新的ClassLoader实例,来加载新编译的Servlet类。之后的请求都会由这个新的Servlet来处理,这样就实现了新旧JSP的切换。HTTP服务是无状态的,所以JSP的场景基本上都是一次性消费,这种通过创建新的ClassLoader来“替换”class的做法行得通,但是对于其他应用,比如Spring框架,即便这样做了,对象多数是单例,对于内存中已经创建好的对象,我们无法通过这种创建新的ClassLoader实例的方法来修改对象行为。我就是想不重启应用加个日志打印,就这么难吗?Java对象行为既然JSP的办法行不通,那我们来看看还有没有其他的办法。仔细想想,我们会发现,文章开头的问题本质上是动态改变内存中已存在对象的行为的问题。所以,我们得先弄清楚JVM中和对象行为有关的地方在哪里,有没有更改的可能性。我们都知道,对象使用两种东西来描述事物:行为和属性。举个例子:public class Person{ private int age; private String name; public void speak(String str) { System.out.println(str); } public Person(int age, String name) { this.age = age; this.name = name; }}上面Person类中age和name是属性,speak是行为。对象是类的事例,每个对象的属性都属于对象本身,但是每个对象的行为却是公共的。举个例子,比如我们现在基于Person类创建了两个对象,personA和personB:Person personA = new Person(43, “lixunhuan”);personA.speak(“我是李寻欢”);Person personB = new Person(23, “afei”);personB.speak(“我是阿飞”);personA和personB有各自的姓名和年龄,但是有共同的行为:speak。想象一下,如果我们是Java语言的设计者,我们会怎么存储对象的行为和属性呢?“很简单,属性跟着对象走,每个对象都存一份。行为是公共的东西,抽离出来,单独放到一个地方。”“咦?抽离出公共的部分,跟代码复用好像啊。”“大道至简,很多东西本来都是殊途同归。”也就是说,第一步我们首先得找到存储对象行为的这个公共的地方。一番搜索之后,我们发现这样一段描述:Method area is created on virtual machine startup, shared among all Java virtual machine threads and it is logically part of heap area. It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors.Java的对象行为(方法、函数)是存储在方法区的。“方法区中的数据从哪来?”“方法区中的数据是类加载时从class文件中提取出来的。”“class文件从哪来?”“从Java或者其他符合JVM规范的源代码中编译而来。”“源代码从哪来?”“废话,当然是手写!”“倒着推,手写没问题,编译没问题,至于加载……有没有办法加载一个已经加载过的类呢?如果有的话,我们就能修改字节码中目标方法所在的区域,然后重新加载这个类,这样方法区中的对象行为(方法)就被改变了,而且不改变对象的属性,也不影响已经存在对象的状态,那么就可以搞定这个问题了。可是,这岂不是违背了JVM的类加载原理?毕竟我们不想改变ClassLoader。”“少年,可以去看看java.lang.instrument.Instrumentation。”java.lang.instrument.Instrumentation看完文档之后,我们发现这么两个接口:redefineClasses和retransformClasses。一个是重新定义class,一个是修改class。这两个大同小异,看reDefineClasses的说明:This method is used to replace the definition of a class without reference to the existing class file bytes, as one might do when recompiling from source for fix-and-continue debugging. Where the existing class file bytes are to be transformed (for example in bytecode instrumentation) retransformClasses should be used.都是替换已经存在的class文件,redefineClasses是自己提供字节码文件替换掉已存在的class文件,retransformClasses是在已存在的字节码文件上修改后再替换之。当然,运行时直接替换类很不安全。比如新的class文件引用了一个不存在的类,或者把某个类的一个field给删除了等等,这些情况都会引发异常。所以如文档中所言,instrument存在诸多的限制:The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance. These restrictions maybe be lifted in future versions. The class file bytes are not checked, verified and installed until after the transformations have been applied, if the resultant bytes are in error this method will throw an exception.我们能做的基本上也就是简单修改方法内的一些行为,这对于我们开头的问题,打印一段日志来说,已经足够了。当然,我们除了通过reTransform来打印日志,还能做很多其他非常有用的事情,这个下文会进行介绍。那怎么得到我们需要的class文件呢?一个最简单的方法,是把修改后的Java文件重新编译一遍得到class文件,然后调用redefineClasses替换。但是对于没有(或者拿不到,或者不方便修改)源码的文件我们应该怎么办呢?其实对于JVM来说,不管是Java也好,Scala也好,任何一种符合JVM规范的语言的源代码,都可以编译成class文件。JVM的操作对象是class文件,而不是源码。所以,从这种意义上来讲,我们可以说“JVM跟语言无关”。既然如此,不管有没有源码,其实我们只需要修改class文件就行了。直接操作字节码Java是软件开发人员能读懂的语言,class字节码是JVM能读懂的语言,class字节码最终会被JVM解释成机器能读懂的语言。无论哪种语言,都是人创造的。所以,理论上(实际上也确实如此)人能读懂上述任何一种语言,既然能读懂,自然能修改。只要我们愿意,我们完全可以跳过Java编译器,直接写字节码文件,只不过这并不符合时代的发展罢了,毕竟高级语言设计之始就是为我们人类所服务,其开发效率也比机器语言高很多。对于人类来说,字节码文件的可读性远远没有Java代码高。尽管如此,还是有一些杰出的程序员们创造出了可以用来直接编辑字节码的框架,提供接口可以让我们方便地操作字节码文件,进行注入修改类的方法,动态创造一个新的类等等操作。其中最著名的框架应该就是ASM了,cglib、Spring等框架中对于字节码的操作就建立在ASM之上。我们都知道,Spring的AOP是基于动态代理实现的,Spring会在运行时动态创建代理类,代理类中引用被代理类,在被代理的方法执行前后进行一些神秘的操作。那么,Spring是怎么在运行时创建代理类的呢?动态代理的美妙之处,就在于我们不必手动为每个需要被代理的类写代理类代码,Spring在运行时会根据需要动态地创造出一个类,这里创造的过程并非通过字符串写Java文件,然后编译成class文件,然后加载。Spring会直接“创造”一个class文件,然后加载,创造class文件的工具,就是ASM了。到这里,我们知道了用ASM框架直接操作class文件,在类中加一段打印日志的代码,然后调用retransformClasses就可以了。BTrace截止到目前,我们都是停留在理论描述的层面。那么如何进行实现呢?先来看几个问题:在我们的工程中,谁来做这个寻找字节码,修改字节码,然后reTransform的动作呢?我们并非先知,不可能知道未来有没有可能遇到文章开头的这种问题。考虑到性价比,我们也不可能在每个工程中都开发一段专门做这些修改字节码、重新加载字节码的代码。如果JVM不在本地,在远程呢?如果连ASM都不会用呢?能不能更通用一些,更“傻瓜”一些。幸运的是,因为有BTrace的存在,我们不必自己写一套这样的工具了。什么是BTrace呢?BTrace已经开源,项目描述极其简短:A safe, dynamic tracing tool for the Java platform.BTrace是基于Java语言的一个安全的、可提供动态追踪服务的工具。BTrace基于ASM、Java Attach Api、Instruments开发,为用户提供了很多注解。依靠这些注解,我们可以编写BTrace脚本(简单的Java代码)达到我们想要的效果,而不必深陷于ASM对字节码的操作中不可自拔。看BTrace官方提供的一个简单例子:拦截所有java.io包中所有类中以read开头的方法,打印类名、方法名和参数名。当程序IO负载比较高的时候,就可以从输出的信息中看到是哪些类所引起,是不是很方便?package com.sun.btrace.samples;import com.sun.btrace.annotations.;import com.sun.btrace.AnyType;import static com.sun.btrace.BTraceUtils.;/** * This sample demonstrates regular expression * probe matching and getting input arguments * as an array - so that any overload variant * can be traced in “one place”. This example * traces any “readXX” method on any class in * java.io package. Probed class, method and arg * array is printed in the action. /@BTrace public class ArgArray { @OnMethod( clazz="/java\.io\../", method="/read./" ) public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) { println(pcn); println(pmn); printArray(args); }}再来看另一个例子:每隔2秒打印截止到当前创建过的线程数。package com.sun.btrace.samples;import com.sun.btrace.annotations.;import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.annotations.Export;/** * This sample creates a jvmstat counter and * increments it everytime Thread.start() is * called. This thread count may be accessed * from outside the process. The @Export annotated * fields are mapped to jvmstat counters. The counter * name is “btrace.” + <className> + “.” + <fieldName> */ @BTrace public class ThreadCounter { // create a jvmstat counter using @Export @Export private static long count; @OnMethod( clazz=“java.lang.Thread”, method=“start” ) public static void onnewThread(@Self Thread t) { // updating counter is easy. Just assign to // the static field! count++; } @OnTimer(2000) public static void ontimer() { // we can access counter as “count” as well // as from jvmstat counter directly. println(count); // or equivalently … println(Counters.perfLong(“btrace.com.sun.btrace.samples.ThreadCounter.count”)); }}看了上面的用法是不是有所启发?忍不住冒出来许多想法。比如查看HashMap什么时候会触发rehash,以及此时容器中有多少元素等等。有了BTrace,文章开头的问题可以得到完美的解决。至于BTrace具体有哪些功能,脚本怎么写,这些Git上BTrace工程中有大量的说明和举例,网上介绍BTrace用法的文章更是恒河沙数,这里就不再赘述了。我们明白了原理,又有好用的工具支持,剩下的就是发挥我们的创造力了,只需在合适的场景下合理地进行使用即可。既然BTrace能解决上面我们提到的所有问题,那么BTrace的架构是怎样的呢?BTrace主要有下面几个模块:BTrace脚本:利用BTrace定义的注解,我们可以很方便地根据需要进行脚本的开发。Compiler:将BTrace脚本编译成BTrace class文件。Client:将class文件发送到Agent。Agent:基于Java的Attach Api,Agent可以动态附着到一个运行的JVM上,然后开启一个BTrace Server,接收client发过来的BTrace脚本;解析脚本,然后根据脚本中的规则找到要修改的类;修改字节码后,调用Java Instrument的reTransform接口,完成对对象行为的修改并使之生效。整个BTrace的架构大致如下:BTrace最终借Instruments实现class的替换。如上文所说,出于安全考虑,Instruments在使用上存在诸多的限制,BTrace也不例外。BTrace对JVM来说是“只读的”,因此BTrace脚本的限制如下:不允许创建对象不允许创建数组不允许抛异常不允许catch异常不允许随意调用其他对象或者类的方法,只允许调用com.sun.btrace.BTraceUtils中提供的静态方法(一些数据处理和信息输出工具)不允许改变类的属性不允许有成员变量和方法,只允许存在static public void方法不允许有内部类、嵌套类不允许有同步方法和同步块不允许有循环不允许随意继承其他类(当然,java.lang.Object除外)不允许实现接口不允许使用assert不允许使用Class对象如此多的限制,其实可以理解。BTrace要做的是,虽然修改了字节码,但是除了输出需要的信息外,对整个程序的正常运行并没有影响。ArthasBTrace脚本在使用上有一定的学习成本,如果能把一些常用的功能封装起来,对外直接提供简单的命令即可操作的话,那就再好不过了。阿里的工程师们早已想到这一点,就在去年(2018年9月份),阿里巴巴开源了自己的Java诊断工具——Arthas。Arthas提供简单的命令行操作,功能强大。究其背后的技术原理,和本文中提到的大致无二。Arthas的文档很全面,想详细了解的话可以戳这里。本文旨在说明Java动态追踪技术的来龙去脉,掌握技术背后的原理之后,只要愿意,各位读者也可以开发出自己的“冰封王座”出来。尾声:三生万物现在,让我们试着站在更高的地方“俯瞰”这些问题。Java的Instruments给运行时的动态追踪留下了希望,Attach API则给运行时动态追踪提供了“出入口”,ASM则大大方便了“人类”操作Java字节码的操作。基于Instruments和Attach API前辈们创造出了诸如JProfiler、Jvisualvm、BTrace、Arthas这样的工具。以ASM为基础发展出了cglib、动态代理,继而是应用广泛的Spring AOP。Java是静态语言,运行时不允许改变数据结构。然而,Java 5引入Instruments,Java 6引入Attach API之后,事情开始变得不一样了。虽然存在诸多限制,然而,在前辈们的努力下,仅仅是利用预留的近似于“只读”的这一点点狭小的空间,仍然创造出了各种大放异彩的技术,极大地提高了软件开发人员定位问题的效率。计算机应该是人类有史以来最伟大的发明之一,从电磁感应磁生电,到高低电压模拟0和1的比特,再到二进制表示出几种基本类型,再到基本类型表示出无穷的对象,最后无穷的对象组合交互模拟现实生活乃至整个宇宙。两千五百年前,《道德经》有言:“道生一,一生二,二生三,三生万物。”两千五百年后,计算机的发展过程也大抵如此吧。作者简介高扬,2017年加入美团打车,负责美团打车结算系统的开发。 ...

March 1, 2019 · 3 min · jiezi

SpringBoot+jsp项目启动出现404

通过maven创建springboot项目启动出现404application.properties配置spring.mvc.view.prefix=/WEB-INF/jsp/spring.mvc.view.suffix=.jsp项目结构控制器方法package com.example.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;@Controllerpublic class IndexController { @RequestMapping("/") public String index() { return “index”; }}启动项目访问localhost:8080,出现404Whitelabel Error PageThis application has no explicit mapping for /error, so you are seeing this as a fallback.Thu Feb 28 22:59:29 CST 2019There was an unexpected error (type=Not Found, status=404).No message available解决方法pom.xml添加依赖<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId></dependency><dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId></dependency>clean并刷新maven重启并访问localhost:8080

March 1, 2019 · 1 min · jiezi

vue scrollTop失效的问题

首先:vue中如果直接设置docuemnt.docuemntElement.scrolTop = 100;在手机上是行不通的。需要明确一下几点:页面指定了DOCTYPE时,使用document.documentElement。页面没指定DOCTYPE时,使用document.body。其次:使用 this.$nextTickthis.$nextTick(() => { document.body.scrollTop = 0;}); 或者:changeScrollTop() { this.$nextTick((length) => { document.documentElement.scrollTop += length })这样即可设置scrollTop

January 4, 2019 · 1 min · jiezi